package com.example.sys.attachment.service.impl;

import com.example.core.utils.IdGenerator;
import com.example.core.utils.SpringBeanUtils;
import com.example.core.utils.StringUtils;
import com.example.sys.attachment.service.SysFileService;
import io.minio.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/***
 * Minio文件存储
 */
public class SysFileMiniIoServiceImpl implements SysFileService {

    Logger logger = LoggerFactory.getLogger(getClass());

    private Environment environment;
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;
    private MinioClient minioClient;

    public Environment getEnvironment() {
        if (this.environment == null) {
            this.environment = SpringBeanUtils.getApplicationContext().getEnvironment();
        }
        return environment;
    }

    public String getEndpoint() {
        if (StringUtils.isEmpty(this.endpoint)) {
            this.endpoint = getEnvironment().getProperty("file.minio.endpoint");
        }
        return endpoint;
    }

    public String getAccessKey() {
        if (StringUtils.isEmpty(this.accessKey)) {
            this.accessKey = getEnvironment().getProperty("file.minio.accessKey");
        }
        return accessKey;
    }

    public String getSecretKey() {
        if (StringUtils.isEmpty(this.secretKey)) {
            this.secretKey = getEnvironment().getProperty("file.minio.secretKey");
        }
        return secretKey;
    }

    public String getBucketName() {
        if (StringUtils.isEmpty(this.bucketName)) {
            this.bucketName = getEnvironment().getProperty("file.minio.bucketName");
        }
        return bucketName;
    }

    public MinioClient getMinioClient() {
        if (this.minioClient == null) {
            this.minioClient = MinioClient.builder().endpoint(getEndpoint()).credentials(getAccessKey(), getSecretKey()).build();
        }
        return minioClient;
    }

    /***
     * 上传文件到Minio
     * @param file
     * @return
     * @throws Exception
     */
    @Override
    public String write(MultipartFile file) throws Exception {
        String uuid = IdGenerator.generateStringId();
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(getBucketName()).object(uuid).contentType(file.getContentType()).stream(inputStream, inputStream.available(), -1).build();
            ObjectWriteResponse objectWriteResponse = getMinioClient().putObject(putObjectArgs);
            uuid = objectWriteResponse.object();
        } catch (Exception e) {
            logger.error("上传文件到Minio失败", e.getMessage());
            throw e;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return uuid;
    }


    /***
     * 读取Minio文件
     * @param path
     * @return
     * @throws Exception
     */
    @Override
    public byte[] read(String path) throws Exception {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try{
            GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(getBucketName()).object(path).build();
            GetObjectResponse getObjectResponse = getMinioClient().getObject(getObjectArgs);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = getObjectResponse.read(buf)) != -1) {
                os.write(buf, 0, len);
            }
        }catch (Exception e){
            logger.error("读取Minio文件失败", e.getMessage());
            throw e;
        }
        return os.toByteArray();
    }


    /***
     * 删除Minio文件
     * @param path
     * @throws Exception
     */
    @Override
    public void delete(String path) throws Exception {
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(getBucketName()).object(path).build();
        getMinioClient().removeObject(removeObjectArgs);
    }
}
